package demo.java.lang.management.vo;

import demo.java.lang.management.jvm.AppTraceConfig;
import demo.java.lang.management.jvm.XdcsPropertiesParser;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.RollingFileAppender;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author mandy.hu
 *
 */

public class XdcsLoggerUtil {

	private static Map<String, XdcsLogger> xdcsLoggerMap = new HashMap<String, XdcsLogger>();

	private static XdcsLogger doNothing = new XdcsLogger(null);
	private static List<String> defaultBlockTypeList = new ArrayList(){
		{
			add("trace");
			add("monitor");
			add("storeMonitor");
			add("clientMonitor");
		}
	};

	static {
		boolean log4jBlock = XdcsPropertiesParser.getLog4jBlockSwitch();
		if(log4jBlock){
			Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
				@Override
				public void run() {
					LogManager.shutdown();
				}
			}));
		}
	}

	public static void dealWithLogger(Map<String, String> urlMap) {
        if (urlMap!=null){
            Iterator<Entry<String, String>> iter = urlMap.entrySet().iterator();
            while (iter.hasNext()) {
                Entry<String, String> entry = (Entry<String, String>) iter.next();
                String val = (String)entry.getValue();
                getLoggerByName(val, AppTraceConfig.getLocalConfig().getLogDir());
            }
        }
	}

	public static XdcsLogger getLoggerByName(String type, String logDir) {

        if (!AppTraceConfig.getLocalConfig().isHasXdcsPropFile()){
            return doNothing;
        }

		if (StringUtils.equalsIgnoreCase(type, "other")) {
			type = "trace";
		}
		String loggerName = "xdcs-"+type+"-logger";
		if (xdcsLoggerMap.get(loggerName)!=null) {
			return xdcsLoggerMap.get(loggerName);
		}

		Logger logger = Logger.getLogger(loggerName);
		logger.removeAllAppenders();
		logger.setLevel(Level.INFO);
		logger.setAdditivity(false);
		// 生成新的Appender
		RollingFileAppender appender = new TimedBufferedRollingFileAppender();
		PatternLayout layout = new PatternLayout();
		// log的输出形式
		String conversionPattern = "%m%n";
		layout.setConversionPattern(conversionPattern);
		appender.setLayout(layout);
		// log输出路径
		appender.setFile(logDir + "/trace/logs/" + type +"-"+ AppTraceConfig.getLocalConfig().getAppName() +"-log.out");
		// log的文字
		appender.setEncoding("UTF-8");
		// true:在已存在log文件后面追加 false:新log覆盖以前的log
		appender.setAppend(true);

		boolean log4jBlock = XdcsPropertiesParser.getLog4jBlockSwitch();
		if(log4jBlock && switchLog4jBufferType(type)){
			appender.setBufferedIO(true);
			appender.setBufferSize(1024 * 1024);//1M
		}

		// 适用当前配置
		appender.activateOptions();
		appender.setMaxBackupIndex(1);
		if (StringUtils.equals(type,"static") || StringUtils.equals(type,"clientad")) {
			appender.setMaxFileSize("20GB");
		}else if (StringUtils.equals(type,"ad") || StringUtils.equals(type,"play") || StringUtils.equals(type,"adClickTopic")) {
			appender.setMaxFileSize("8GB");
		} else if (StringUtils.equals(type,"trace")) {
			appender.setMaxFileSize("2GB");
		}else {
			appender.setMaximumFileSize(1024*1024*1024);
		}
		if (AppTraceConfig.getLocalConfig()!=null&&
				AppTraceConfig.getLocalConfig().getLog2SizeMapping()!=null&&
				AppTraceConfig.getLocalConfig().getLog2SizeMapping().get(type)!=null) {
			appender.setMaxFileSize(AppTraceConfig.getLocalConfig().getLog2SizeMapping().get(type));
		}
		String appenderName = type + "FileAppender";
		appender.setName(appenderName);
		// 将新的Appender加到Logger中
		logger.addAppender(appender);

		XdcsLogger xdcsLogger = new XdcsLogger(logger);

		xdcsLoggerMap.put(loggerName, xdcsLogger);
		return xdcsLogger;
	}

	private static boolean switchLog4jBufferType(String type) {
		if(StringUtils.isBlank(type)){
			return false;
		}
		List<String> blockTypeList = XdcsPropertiesParser.getLog4jBlockType();
		if(blockTypeList==null || blockTypeList.size()==0){
			return defaultBlockTypeList.contains(type);
		}
		return blockTypeList.contains(type);
	}


}
